package vnc.server;

import java.awt.AWTException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

import vnc.server.rfb.JavaInStream;
import vnc.server.rfb.JavaOutStream;
import vnc.server.rfb.PixelFormat;
import vnc.server.rfb.messages.ClientCutTextMessage;
import vnc.server.rfb.messages.FramebufferUpdateMessage;
import vnc.server.rfb.messages.FramebufferUpdateRequestMessage;
import vnc.server.rfb.messages.KeyEventMessage;
import vnc.server.rfb.messages.Message;
import vnc.server.rfb.messages.PointerEventMessage;
import vnc.server.rfb.messages.SetEncodingsMessage;
import vnc.server.rfb.messages.SetPixelFormatMessage;

public class Main {
	
	protected int port = 5900;
	
	public static Message update;
	
	public void Start()
	{
		try
		{
			//TODO: clean up code. remove useless objects.
            ServerSocket serverSocket = new ServerSocket(port);
            Socket clientSocket = serverSocket.accept();
        	OutputStream out = clientSocket.getOutputStream();
        	InputStream in = clientSocket.getInputStream();
        	DataInputStream din = new DataInputStream(in);
        	DataOutputStream dout = new DataOutputStream(out);
        	BufferedReader bin = new BufferedReader(new InputStreamReader(in));
        	BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(out));
        	JavaOutStream jout = new JavaOutStream(out);
        	JavaInStream jin = new JavaInStream(in);
        	
        	bout.write("RFB 003.003\n");
        	bout.flush();
        	String answer = bin.readLine();
        	System.out.println(answer);
        	//no auth
        	dout.writeInt(1);
        	byte shared = din.readByte();
        	short width = 1024;
        	short height = 768;
        	dout.writeShort(width);
        	dout.writeShort(height);
        	//set pixel format
        	new PixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6).write(jout);
        	jout.flush();
        	//set name
        	String name = "hi marat";
        	jout.writeString(name);
        	jout.flush();
        	Message messages[] = new Message[127];
        	messages[0] = new SetPixelFormatMessage(clientSocket);
        	messages[2] = new SetEncodingsMessage(clientSocket);
        	messages[3] = new FramebufferUpdateRequestMessage(clientSocket);
        	messages[4] = new KeyEventMessage(clientSocket);
        	messages[5] = new PointerEventMessage(clientSocket);
        	messages[6] = new ClientCutTextMessage(clientSocket);
        	
        	update = new FramebufferUpdateMessage(clientSocket);
        	
        	Main.update.process();   	
        	
        	while (true)
        	{
        		int messageType = din.readByte();
        		if (messages[messageType] != null)
        		{
        			
        			messages[messageType].process();
        		}
        		else
        			System.err.println("Not supported message " + messageType);
        		if (false) break;
        	}
        	
            out.close();
            in.close();
	        
	        clientSocket.close();
	        serverSocket.close();		
	    }
	    catch(IOException e)
	    {
	    	System.err.println("Exception while communication");
	    } catch (AWTException e) {
			e.printStackTrace();
		}
	}
	
    public static void main(String[] args) throws IOException {

    	new Main().Start();
    }
}